package com.wcbtest.webs;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSchException;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;

@ServerEndpoint("/terminal")
@Component
public class TerminalEndpoint {
    //private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<>());
    private static final HashMap<String, HashMap<String, Object>> clientData = new HashMap<>();

    /***
     * 连接建立时执行的操作
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("获取访客:" + session.getId());
        HashMap<String, Object> map = new HashMap<>();
        map.put("clientSession", session);
        clientData.put(session.getId(), map);
    }


    /***
     * 收到客户端消息执行的操作
     */
    @OnMessage
    public void onMessage(String command, Session session) {
        System.out.println("获取访客:" + session.getId());
        System.out.println("收到客户端消息:" + command);
        // 处理客户端信息
        try {
            sendSSH(command, session);
        } catch (Exception e) {
            sendClient(session, e.getMessage());
        }
    }


    public void sendSSH(String command, Session session) {
        try {
            Channel jschChannel = null;
            if (clientData.containsKey(session.getId())) {
                HashMap<String, Object> map = clientData.get(session.getId());
                if (map.containsKey("jschChannel")) {
                    jschChannel = (Channel) map.get("jschChannel");
                    System.out.println("获取用户session");
                } else {
                    jschChannel = initJschShellChannel();
                    map.put("jschChannel", jschChannel);
                }
            } else {
                throw new RuntimeException("当前用户不存在");
            }

            // 写入命令
            OutputStream out = jschChannel.getOutputStream();
            out.write((command + "\n").getBytes());
            out.flush();

            // 读取输出
            InputStream in = jschChannel.getInputStream();
            readOutput(session, in);

            //
            //// 超时后发送Ctrl+C（ASCII码为3）
            //if (isCommandRunning(jschChannel)) {
            //    out.write(3); // 发送Ctrl+C
            //    out.flush();
            //
            //    // 读取剩余输出
            //    //readOutput(jschChannel.getInputStream(), 1000);
            //}


            //// 获取输入输出流
            //OutputStream out = jschChannel.getOutputStream();  // 发送命令
            //// 执行命令
            ////out.write(command.getBytes());
            //out.write((command + "\n").getBytes());
            ////out.write("cd /home\n".getBytes());
            //out.flush();
            //
            //InputStream in = jschChannel.getInputStream();     // 接收输出
            //
            //System.out.println(in.available());
            //// 读取命令的输出结果
            // outClient(session, jschChannel, in);
            //channel.disconnect();
            //jschChannel.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void outClient(Session session, Channel channel, InputStream in) throws IOException {
        byte[] tmp = new byte[1024];
        while (true) {
            while (in.available() > 0) {
                int i = in.read(tmp, 0, 1024);
                if (i < 0) {
                    break;
                }
                String msg = new String(tmp, 0, i);
                System.out.println(msg);
                sendClient(session, msg);
            }
            if (channel.isClosed()) {
                String msg = "Exit-status: " + channel.getExitStatus();
                System.out.println(msg);
                sendClient(session, msg);
                break;
            }
            try {
                Thread.sleep(500);
            } catch (Exception ee) {
            }
        }
    }

    // 检查命令是否仍在运行
    private boolean isCommandRunning(Channel channel) {
        try {
            // 尝试获取退出状态，若返回-1表示命令仍在运行
            return channel.getExitStatus() == -1;
        } catch (Exception e) {
            return false;
        }
    }
    // 读取输出流（添加超时机制）
    private void readOutput(Session session, InputStream inputStream) throws IOException {
        StringBuilder result = new StringBuilder();
        byte[] buffer = new byte[4096];
        long timeout = System.currentTimeMillis() + 5000; // 5秒超时
        while (System.currentTimeMillis() < timeout) {
            if (inputStream.available() > 0) {
                int bytesRead = inputStream.read(buffer);
                if (bytesRead > 0) {
                    sendClient(session, new String(buffer, 0, bytesRead, "UTF-8"));
                    timeout = System.currentTimeMillis() + 5000; // 重置超时
                }
            } else {
                try {
                    Thread.sleep(500); // 短暂等待，避免CPU占用过高
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
    }

    // 优化后的流读取方法（添加超时和缓冲处理）
    private String readOutput(InputStream inputStream, long timeoutMillis) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        byte[] chunk = new byte[4096];
        long startTime = System.currentTimeMillis();

        while (true) {
            // 1. 检查是否有数据可读
            if (inputStream.available() > 0) {
                int bytesRead = inputStream.read(chunk);
                if (bytesRead > 0) {
                    buffer.write(chunk, 0, bytesRead);
                    startTime = System.currentTimeMillis(); // 重置超时计时器
                }
            }
            // 2. 检查是否超时（无新数据）
            if (System.currentTimeMillis() - startTime > timeoutMillis) {
                break;
            }
            // 3. 短暂休眠避免CPU占用过高
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }

        return buffer.toString("UTF-8");
    }

    private Channel initJschShellChannel() throws JSchException {
        com.jcraft.jsch.Session jschSession =JSchUtils2.initJschSession();
        // 创建交互式shell通道
        Channel channel = jschSession.openChannel("shell");
        //channel.setPty(true);
        channel.connect();
        return channel;
    }



    /***
     * 向客户端发送信息
     */
    //@Scheduled(fixedRate = 2000)
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMsg() throws IOException {
        System.out.println("向客户端发送信息");
    }


    @OnError
    public void onError(Session session, Throwable error) {
        sendClient(session, "服务器出现异常：" + error.getMessage());
        System.out.println("获取访客:" + session.getId());
        error.printStackTrace();
    }

    /***
     * 连接关闭时执行的操作
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        System.out.println("获取访客:" + session.getId());
        System.out.println("终端连接关闭:" + session.getId());
        clientData.remove(session.getId());
    }


    private void sendClient(Session session, String str) {
        try {
            session.getBasicRemote().sendText(str);
        } catch (Exception e) {
            throw new RuntimeException("发送信息到客户端失败");
        }
    }


}
